#!/usr/bin/env python
#-*- encoding: gbk -*-
#    

import ConfigParser
import logging
import time, os
from logging.handlers import RotatingFileHandler
import platform

#global
log_msg_root = '_msg_log_'

#log_stderr_format =  '$RESET$COLOR<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s'
log_stderr_format =  '$COLOR$BOLD<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s>$RESET$COLOR<%(filename)s:%(lineno)d>%(message)s'
#log_stderr_format = "$COLOR%(levelname)s $RESET %(asctime)s $BOLD$COLOR%(name)s$RESET %(message)s"

if platform.system() == 'Windows':
	log_file_format = '<%(levelname)s><%(name)s:%(process)d>%(message)s'
else:
	log_file_format = '%(asctime)s <%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s'


# for colorful stderr output, copy from http://stackoverflow.com/questions/384076/how-can-i-make-the-python-logging-output-to-be-colored
# by rrt

BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
RESET_SEQ = "\033[0m"
#COLOR_SEQ = "\033[1;%dm"         # color & bold
COLOR_SEQ = "\033[0;%dm"        # color only
BOLD_SEQ = "\033[1m" 

COLORS={
	'WARNING':WHITE,
	'INFO':YELLOW,
	'DEBUG':GREEN,
	'CRITICAL':YELLOW,
	'ERROR':RED,
	'RED':RED,
	'GREEN':GREEN,
	'YELLOW':YELLOW,
	'BLUE':BLUE,
	'MAGENTA':MAGENTA,
	'CYAN':CYAN,
	'WHITE':WHITE,}
"""
COLORS = {
	'INFO': YELLOW,
	'DEBUG': GREEN,
	'ERROR': RED } 
	"""

class ColoredFormatter(logging.Formatter):
	def __init__(self, *args, **kwargs):
		logging.Formatter.__init__(self, *args, **kwargs)

	def format(self, record):
		levelname = record.levelname
		color     = COLOR_SEQ % (30 + COLORS[levelname])
		message   = logging.Formatter.format(self, record)
		#print "1--" + repr(message)
		message   = message.replace("$RESET", RESET_SEQ)\
				.replace("$BOLD",  BOLD_SEQ)\
				.replace("$COLOR", color)
		#print "2--" + repr(message)
		#for k,v in COLORS.items():
		#	message = message.replace("$" + k,    COLOR_SEQ % (v+30))\
		#			.replace("$BG" + k,  COLOR_SEQ % (v+40))\
		#			.replace("$BG-" + k, COLOR_SEQ % (v+40))
		#print "3--" + repr(message)
		return message + RESET_SEQ



#This class copy form liup's blog http://hi.baidu.com/dalier/blog/item/68419d64b98604faf63654e4.html
#by rrt on 2010-12-3

class DateRotatingFileHandler(RotatingFileHandler):
	def __init__(self , filename , mode='a' , maxBytes=0, backupCount=0, encoding=None):
		self.current = time.strftime("%Y%m%d" , time.localtime(time.time()))
		self.path = os.path.dirname(filename)
		self.filename = os.path.basename(filename)
		newdir = os.path.join(self.path , self.current)
		softlink = os.path.join(self.path, 'current')
		if not os.access(newdir , os.X_OK):
			os.mkdir(newdir)
		try:
			os.symlink(newdir ,softlink)
		except:
			os.system("rm -f " + softlink)
			os.symlink(newdir ,softlink)
		newfile = os.path.join(newdir , self.filename)
		RotatingFileHandler.__init__(self, newfile , mode, maxBytes , backupCount , encoding)

	def doRollover(self):
		#print "doRollover , current=%s , filename=%s"%(self.current , self.baseFilename)
		self.stream.close()
		self.current = time.strftime("%Y%m%d" , time.localtime(time.time()))
		
		#Modified by rrt on 2010-12-4 for a log path bug: /'20101204' 
		#repr() is not needed , time.strftime() return a string not a integer
		#newdir = os.path.join(self.path , repr(self.current))
		newdir = os.path.join(self.path , self.current)
		if not os.access(newdir , os.X_OK):
			os.mkdir(newdir)
		self.baseFilename = os.path.join(newdir , self.filename)

		if self.encoding:
			self.stream = codecs.open(self.baseFilename, 'w', self.encoding)
		else:
			self.stream = open(self.baseFilename, 'w')

	def shouldRollover(self, record):
		if RotatingFileHandler.shouldRollover(self , record):
			RotatingFileHandler.doRollover(self)

		t = time.strftime("%Y%m%d" , time.localtime(time.time()))
		if (cmp(self.current , t) < 0) :
			return 1

		return 0


def init_log(prefix, cfg_file, type,level):
	global log_msg_root, log_file_format, log_stderr_format

	cf = ConfigParser.ConfigParser()
	cf.read(cfg_file)
	config = {}

	# we can use
	#	= cf.get(prefix, 'level').split('#')[0].strip()
	# to enable "#" to comment behind a value string.

	try:
		config['level'] = cf.get(prefix, 'level')
	except:
		config['level'] = cf.get(log_msg_root, 'level')

	try:
		config['file'] = cf.get(prefix, 'file')
	except:
		path = cf.get(log_msg_root, 'file')
		path = os.path.dirname(path)
		config['file'] = os.path.join(path, prefix+'.log')
		
	try:
		config['stderr'] = cf.getint(prefix, 'stderr')
	except:
		config['stderr'] = cf.getint(log_msg_root, 'stderr')

	try:
		config['syslog'] = cf.getint(prefix, 'syslog')
	except:
		config['syslog'] = cf.getint(log_msg_root, 'syslog')

	try:
		config['file_size'] = cf.getint(prefix, 'file_size')
	except:
		config['file_size'] = cf.getint(log_msg_root, 'file_size')

	try:
		config['file_cnt'] = cf.getint(prefix, 'file_counter')
	except:
		config['file_cnt'] = cf.getint(log_msg_root, 'file_counter')
	
	print config

	#new a root logger
	logger = logging.getLogger(prefix)
	#set root logger level
	if config['level'] == 'debug':
		logger.setLevel(logging.DEBUG)
	elif config['level'] == 'info':
		logger.setLevel(logging.INFO)
	else:
		logger.setLevel(logging.ERROR)
	#new a log file handle
	log_handler = DateRotatingFileHandler(config['file'], mode="a", maxBytes = config['file_size']*1024*1024, backupCount=config['file_cnt'])
	#set log file handle format
	formatter = logging.Formatter(log_file_format, datefmt='%Y-%m-%d %H:%M:%S')# '%F %T') jython not work
	log_handler.setFormatter(formatter)
	#add to root logger
	logger.addHandler(log_handler)
	#new a stderr logger if need
	if not config['stderr']:
		return logger
	else:

		formatter = ColoredFormatter(log_stderr_format)
		#formatter = logging.Formatter(log_stderr_format)
		log_handler = logging.StreamHandler()
		log_handler.setFormatter(formatter)
		logger.addHandler(log_handler)
		return logger
	


if __name__ == '__main__':
	global logger

	logger = init_log('test_log_lib', 'msg_log.ini', 0, 0)
	logger.debug('debug rrrrrrrrrrrrrrrrrrrrrrrrrrrt')
	logger.info('info rrrrrrrrrrrrrrrrrrrrrrrrrrrt')
	logger.error('error rrrrrrrrrrrrrrrrrrrrrrrrrrrt')

